Useful Links - ICM42688 Setup

From RidgeRun Developer Wiki

Follow Us On Twitter LinkedIn Email Share this page







This wiki page contains information on how to set up the SRX-IMU00-DEV device from SYSROX for NVIDIA Jetson platforms. The steps are applicable to other platforms with a Linux kernel greater than 5.15.

These instructions target the SPI variant of the ICM42688.

JetPack 6

The next section was tested on the Jetson Orin Nano board running JetPack 6.2 (L4T 36.4.3)

Kernel Customization

First, enable the Linux kernel driver that supports the InvenSense ICM-426xx motion tracking devices over SPI, since the NVIDIA Jetson devices do not enable it by default.

Prepare the necessary directories

First, install the NVIDIA board support package by downloading the Driver Package (BSP) and Sample Root Filesystem from the drivers section on the following link. Extract the downloaded files with the following commands inside a work directory.

mkdir nvidia-jetson

tar xf Jetson_Linux_R36.4.3_aarch64.tbz2 -C nvidia-jetson/
sudo tar xpf Tegra_Linux_Sample-Root-Filesystem_R36.4.3_aarch64.tbz2 -C \
nvidia-jetson/Linux_for_Tegra/rootfs

Now run the following scripts inside the Linux_for_Tegra directory:

cd nvidia-jetson/Linux_for_Tegra

sudo ./tools/l4t_flash_prerequisites.sh

sudo ./apply_binaries.sh

(Optional step) Create a default user:

 sudo ./tools/l4t_create_default_user.sh -u <user_name> -p <password>

Obtaining the kernel sources

To obtain the kernel sources, run the following commands:

cd <install-path>/Linux_for_Tegra/source
./source_sync.sh -k -t jetson_36.4.3

Obtaining the Jetson-Linux toolchain

Then, it is required to download the Jetson-Linux toolchain from the Jetson release page located here. Execute the following commands to download and extract the toolchain:

mkdir $HOME/jetson-toolchain
cd $HOME/jetson-toolchain
wget https://developer.nvidia.com/downloads/embedded/l4t/r36_release_v3.0/toolchain/aarch64--glibc--stable-2022.08-1.tar.bz2
tar xf aarch64--glibc--stable-2022.08-1.tar.bz2

Applying the patches

Before building the kernel, enable support for the InvenSense ICM-426xx SPI driver by applying a patch to the kernel sources, as the support for the sensor ICM-42688-P was added in kernel version 6.10, as shown on this page.

The first thing is to apply this patch to the kernel sources located in the <install path>/Linux_for_Tegra/source/kernel/kernel-jammy-src directory. You can copy the following patch and save it to a .patch file.

From 9976f503c81cbb14aa3e0d1920388dc1915c33ae Mon Sep 17 00:00:00 2001
From: Ridgerun support@ridgerun.com>
Date: Wed, 14 Jan 2026 16:35:47 -0600
Subject: [PATCH] iio: imu: inv_icm42600: add icm42688 support

---
 .../devicetree/bindings/iio/imu/invensense,icm42600.yaml     | 1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h                  | 2 ++
 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c             | 5 +++++
 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c              | 3 +++
 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c              | 3 +++
 5 files changed, 14 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
index 4c1c083d0e92..8b58b152d64a 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -31,6 +31,7 @@ properties:
       - invensense,icm42602
       - invensense,icm42605
       - invensense,icm42622
+      - invensense,icm42688
 
   reg:
     maxItems: 1
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 995a9dc06521..8a3b99de1096 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -22,6 +22,7 @@ enum inv_icm42600_chip {
 	INV_CHIP_ICM42602,
 	INV_CHIP_ICM42605,
 	INV_CHIP_ICM42622,
+	INV_CHIP_ICM42688,
 	INV_CHIP_NB,
 };
 
@@ -303,6 +304,7 @@ struct inv_icm42600_state {
 #define INV_ICM42600_WHOAMI_ICM42602			0x41
 #define INV_ICM42600_WHOAMI_ICM42605			0x42
 #define INV_ICM42600_WHOAMI_ICM42622			0x46
+#define INV_ICM42600_WHOAMI_ICM42688			0x47
 
 /* User bank 1 (MSB 0x10) */
 #define INV_ICM42600_REG_SENSOR_CONFIG0			0x1003
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index ca85fccc9839..e1c86dd894b1 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -87,6 +87,11 @@ static const struct inv_icm42600_hw inv_icm42600_hw[INV_CHIP_NB] = {
 		.name = "icm42622",
 		.conf = &inv_icm42600_default_conf,
 	},
+	[INV_CHIP_ICM42688] = {
+		.whoami = INV_ICM42600_WHOAMI_ICM42688,
+		.name = "icm42688",
+		.conf = &inv_icm42600_default_conf,
+	},
 };
 
 const struct iio_mount_matrix *
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
index 53891010a91d..42d22b14d005 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -84,6 +84,9 @@ static const struct of_device_id inv_icm42600_of_matches[] = {
 	}, {
 		.compatible = "invensense,icm42622",
 		.data = (void *)INV_CHIP_ICM42622,
+	}, {
+		.compatible = "invensense,icm42688",
+		.data = (void *)INV_CHIP_ICM42688,
 	},
 	{}
 };
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
index 323789697a08..7443391f1660 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -80,6 +80,9 @@ static const struct of_device_id inv_icm42600_of_matches[] = {
 	}, {
 		.compatible = "invensense,icm42622",
 		.data = (void *)INV_CHIP_ICM42622,
+	}, {
+		.compatible = "invensense,icm42688",
+		.data = (void *)INV_CHIP_ICM42688,
 	},
 	{}
 };
-- 
2.43.0


Next, add the following line at the end of the default kernel configuration file located in the path <install path>/Linux_for_Tegra/source/kernel/kernel-jammy-src/arch/arm64/configs/defconfig using a text editor of your choice:

CONFIG_INV_ICM42600_SPI=m

to load it as a module.

After that, you need to modify the device-tree of your board, in this case, for the Jetson Orin Nano the device-tree is called tegra234-p3768-0000+p3767-0005-nv.dts and it is located in the folder <install path>/Linux_for_Tegra/source/hardware/nvidia/t23x/nv-public. For this step, create a file in that folder called tegra234-p3768-0000-a0.dtsi. For example, and include the following content in that file:

#include <dt-bindings/gpio/tegra234-gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
	bus@0 {
		spi@3210000 {
			/delete-node/ spi@0;
			icm42688@0 {
				compatible = "invensense,icm42688";
				status = "okay";
				reg = <0x0>;
				spi-max-frequency = <12000000>;
				spi-cpha;
				spi-cpol;
				interrupt-parent = <&gpio>;
				interrupts = <TEGRA234_MAIN_GPIO(I, 6) IRQ_TYPE_EDGE_FALLING>;
				interrupt-names = "INT1";
				controller-data {
					nvidia,enable-hw-based-cs;
					nvidia,rx-clk-tap-delay = <0x10>;
					nvidia,tx-clk-tap-delay = <0x0>;
				};
			};
		};
	};
};

The next step is to include the file we created above in the main file i.e. tegra234-p3768-0000+p3767-0005-nv.dts, like this:

// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES.  All rights reserved.

/dts-v1/;

#include "tegra234-p3768-0000+p3767-0005.dts"
#include "tegra234-p3768-0000+p3767-xxxx-nv-common.dtsi"
#include "tegra234-p3768-0000-a0.dtsi"

/ {
	bus@0 {
		host1x@13e00000 {
			nvdla0@15880000 {
				status = "disabled";
			};

			nvdla1@158c0000 {
				status = "disabled";
			};

			pva0@16000000 {
				status = "disabled";
			};
		};
	};
};

Building the Linux kernel

Then, run the following commands to build the Jetson Linux kernel and its in-tree modules:

cd <install-path>/Linux_for_Tegra/source
export CROSS_COMPILE=$HOME/jetson-toolchain/aarch64--glibc--stable-2022.08-1/bin/aarch64-buildroot-linux-gnu-
make -C kernel

Now, to install the kernel image and its in-tree modules execute the following commands:

export INSTALL_MOD_PATH=<install-path>/Linux_for_Tegra/rootfs/
sudo -E make install -C kernel
cp kernel/kernel-jammy-src/arch/arm64/boot/Image <install-path>/Linux_for_Tegra/kernel/Image

Building the DTBs

To build the DTBs go to the kernel sources directory and run the following commands:

cd <install-path>/Linux_for_Tegra/source
export CROSS_COMPILE=$HOME/jetson-toolchain/aarch64--glibc--stable-2022.08-1/bin/aarch64-buildroot-linux-gnu-
export KERNEL_HEADERS=$PWD/kernel/kernel-jammy-src
make dtbs

Execute the following command to install the dtbs:

cp kernel-devicetree/generic-dts/dtbs/* <install-path>/Linux_for_Tegra/kernel/dtb/

Flashing the device

To flash the board, follow this guide, depending on the device you are using. If it is a Jetson Orin Nano with an SD Card, put the board in forced recovery mode and execute the following command:

sudo ./tools/kernel_flash/l4t_initrd_flash.sh --external-device mmcblk0p1 \
-c tools/kernel_flash/flash_l4t_external.xml -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \
--showlogs --network usb0 jetson-orin-nano-devkit internal

JetPack 5

Kernel Customization

Prepare the necessary directories

First, install the NVIDIA board support package by downloading the Driver Package (BSP) and Sample Root Filesystem from the Jetson Linux R35.6.1 release. Extract the downloaded files with the following commands inside a work directory.

mkdir nvidia-jetson

tar xf Jetson_Linux_R35.6.1_aarch64.tbz2 -C nvidia-jetson/
sudo tar xpf Tegra_Linux_Sample-Root-Filesystem_R35.6.1_aarch64.tbz2 -C \
nvidia-jetson/Linux_for_Tegra/rootfs

Now run the following script inside the Linux_for_Tegra directory:

cd nvidia-jetson/Linux_for_Tegra
sudo ./apply_binaries.sh

(Optional step) Create a default user:

sudo ./tools/l4t_create_default_user.sh -u <user_name> -p <password>

Obtaining the kernel sources

To obtain the kernel sources, run the following commands:

cd nvidia-jetson/Linux_for_Tegra/
./source_sync.sh -k -t jetson_35.6.1

Obtaining the Jetson-Linux toolchain

Download and extract the Jetson-Linux toolchain:

mkdir $HOME/jetson-toolchain
tar xf aarch64--glibc--stable-final.tar.gz -C $HOME/jetson-toolchain

Export the toolchain variables:

export ARCH=arm64
export CROSS_COMPILE=$HOME/jetson-toolchain/bin/aarch64-buildroot-linux-gnu-

Applying the patches

Support for the ICM42688 sensor is not enabled by default in the JetPack 5.1.5 kernel. Apply the same patch used for newer kernels to add ICM42688 support to the inv_icm42600 driver.

Apply the patch in the following directory:

Linux_for_Tegra/sources/kernel/kernel-5.10/

Kernel configuration

Enable the SPI driver as a module:

cd Linux_for_Tegra/sources/kernel/kernel-5.10
make O=kernel_out tegra_defconfig

Add the following line to the configuration:

CONFIG_INV_ICM42600_SPI=m

Then update the configuration:

make O=kernel_out olddefconfig

Device Tree modification

The Jetson Xavier NX Developer Kit (SD card version) uses the following device tree:

tegra194-p3668-0000-p3509-0000.dts

The SPI controller for the 40-pin expansion header is SPI1, located at spi@3210000.

Edit the following file:

hardware/nvidia/platform/t19x/jakku/kernel-dts/common/tegra194-p3668-common.dtsi

Replace the spi@0 (CS0) child node under spi@3210000 with the following content:

spi@0 {
	compatible = "invensense,icm42688";
	status = "okay";
	reg = <0x0>;
	spi-max-frequency = <12000000>;

	spi-cpha;
	spi-cpol;

	interrupt-parent = <&tegra_main_gpio>;
	interrupts = <TEGRA194_MAIN_GPIO(R, 0) IRQ_TYPE_EDGE_FALLING>;
	interrupt-names = "INT1";

	controller-data {
		nvidia,enable-hw-based-cs;
		nvidia,rx-clk-tap-delay = <0x10>;
		nvidia,tx-clk-tap-delay = <0x0>;
	};
};

Building the Linux kernel

Build the kernel and its in-tree modules:

export KSRCDIR=<install-path>/Linux_for_Tegra/sources/kernel/kernel-5.10
make -C $KSRCDIR O=$KSRCDIR/kernel_out -j$(nproc)

Install the kernel modules into the root filesystem:

sudo -E make -C $KSRCDIR O=$KSRCDIR/kernel_out \
modules_install INSTALL_MOD_PATH=../rootfs

Copy the kernel image:

cp $KSRCDIR/kernel_out/arch/arm64/boot/Image \
../kernel/Image

Building the DTBs

Build the device tree blobs:

make -C $KSRCDIR O=$KSRCDIR/kernel_out dtbs -j$(nproc)

Install the DTB:

cp $KSRCDIR/kernel_out/arch/arm64/boot/dts/**/tegra194-p3668-0000-p3509-0000.dtb \
../kernel/dtb/

Flashing the device

Put the Jetson Xavier NX Developer Kit into forced recovery mode and flash the SD card:

cd ../
sudo ./flash.sh jetson-xavier-nx-devkit mmcblk0p1

Installation Check

Pinmux Configuration

Once the board has been flashed successfully, we need to map the SPI ports on the Jetson Orin Nano using Jetson IO:

  • 1. Use Jetson-IO to configure pins:
sudo /opt/nvidia/jetson-io/jetson-io.py
  • 2. Once inside select "Configure Jetson 40-pin Header"
  • 3. Choose "Configure header pins manually".
  • 4. Select "spi1" and save changes.
  • 5. Reboot the system to apply the changes.

Connecting the Hardware

The connection will be as follows (From SRX-IMU00-DEV/ICM42688 to the Jetson 40-pin expansion header):

  • 1. 3V3 pin --> 3.3V (pin 1)
  • 2. GND pin --> GND (any of the following pins: 6, 9, 14, 20, 25, 30, 34 or 39)
  • 3. MOSI/SDI pin --> SPI0_MOSI (pin 19)
  • 4. MISO/SDO pin --> SPI0_MISO (pin 21)
  • 5. CLK/SCL pin --> SPI0_SCK (pin 23)
  • 6. CS pin --> SPI0_CS0* (pin 24)
  • 7. INT pin --> GPIO07 (pin 32)

You can refer to the Jetson Orin Nano Developer Kit Carrier Board Specification to learn more about the 40-pin expansion header connections.

How to load the driver

To load the driver, run the following commands on the board:

sudo modprobe inv-icm42600
sudo modprobe inv-icm42600-spi


Info
Use this only in case that the driver is compiled as a module


Verify it was properly loaded running the next command:

sudo dmesg | grep -i spi 

# Sample output:
[   63.776310] SPI driver inv-icm42600-spi has no spi_device_id for invensense,icm42600
[   63.776343] SPI driver inv-icm42600-spi has no spi_device_id for invensense,icm42602
[   63.776346] SPI driver inv-icm42600-spi has no spi_device_id for invensense,icm42605
[   63.776347] SPI driver inv-icm42600-spi has no spi_device_id for invensense,icm42622
[   63.776348] SPI driver inv-icm42600-spi has no spi_device_id for invensense,icm42688
[   63.776884] inv-icm42600-spi spi0.0: mounting matrix not found: using identity...
[   63.776965] inv-icm42600-spi spi0.0: supply vdd not found, using dummy regulator
[   63.777221] inv-icm42600-spi spi0.0: supply vddio not found, using dummy regulator

Permissions

To use the device, please check the permissions:

sudo chmod -R 777 /sys/bus/iio/devices/iio\:device*
sudo chmod 777 /dev/iio\:device*


Info
This should be done every boot but you can do the following to do it automatically on boot


Add a service to set permissions on /sys virtual directory:

sudo tee /etc/systemd/system/iio-perms.service > /dev/null <<'EOF'
[Unit]
Description=Set permissions for IIO devices
After=multi-user.target
Wants=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'chmod -R 777 /sys/bus/iio/devices/iio:device* || true'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

Enable the service:

sudo systemctl daemon-reload
sudo systemctl enable iio-perms.service
sudo systemctl start iio-perms.service

Create iio group and udev rule to set permission on /dev/iio:

# Create iio group
sudo groupadd -f iio

# Add current user to the group
sudo usermod -aG iio "$USER"

# apply group change:
newgrp iio

Create udev rule:

sudo tee /etc/udev/rules.d/99-iio.rules > /dev/null <<'EOF'
KERNEL=="iio:device*", SUBSYSTEM=="iio", GROUP="iio", MODE="0660"
EOF

Reload udev rules:

sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=iio

Add the iio-icm driver to be loaded on boot:

echo inv-icm42600-spi | sudo tee /etc/modules-load.d/icm42600.conf

Check with the example

Please, use this example to test the connectivity.